<template>
  <div class="h-full">
    <Tabs class="tab-box" v-model:activeKey="dateKey" :animated="true">
      <TabPane key="day">
        <template #tab> 日 </template>
      </TabPane>
      <TabPane key="month">
        <template #tab> 月 </template>
      </TabPane>
      <TabPane key="year">
        <template #tab> 年 </template>
      </TabPane>
      <template #rightExtra>
        <RangePicker class="mr-14px" show-time @change="handleChange" />
      </template>
    </Tabs>
    <div class="ml-20px mr-20px mt-12px" style="height: calc(100% - 72px)">
      <Row :gutter="[13, 13]">
        <Col span="24">
          <Card title="数据总览" class="hover:cursor-pointer">
            <CardGrid
              v-for="(item, index) in list"
              :key="index"
              @click="goDetails(item)"
              class="!p-3"
            >
              <p class="text-sm"> {{ item.title }} </p>
              <p class="text-2xl font-bold">{{ item.value == '' ? 0 : item.value }}</p>
            </CardGrid>
          </Card>
        </Col>
        <Col span="8">
          <TransportChart
            :chartData="chartData.transportDataPointsCountHourly"
            :dateKey="dateKey"
          />
        </Col>
        <Col span="8">
          <RuleChart
            :chartData="chartData.ruleEngineExecutionCountHourly"
            :statsChartData="ruleStatsChartData"
            :dateKey="dateKey"
          />
        </Col>
        <Col span="8">
          <jsChart :chartData="chartData.jsExecutionCountHourly" :dateKey="dateKey" />
        </Col>
        <Col span="8">
          <StorageChart :chartData="chartData.storageDataPointsCountHourly" :dateKey="dateKey" />
        </Col>
        <Col span="8">
          <AlarmChart :chartData="chartData.createdAlarmsCountHourly" :dateKey="dateKey" />
        </Col>
        <Col span="8">
          <NotificationChart :chartData="chartData.emailCountHourly" :dateKey="dateKey" />
        </Col>
      </Row>
    </div>
  </div>
</template>

<script lang="ts" setup>
  import { onMounted, ref, onBeforeUnmount, watch } from 'vue';
  import { Tabs, TabPane, RangePicker, Row, Col, Card, CardGrid } from 'ant-design-vue';
  import { useWebSocket } from '@vueuse/core';
  import { useGo } from '/@/hooks/web/usePage';
  import { find } from '/@/api/thingsborad/api/api';
  import dayjs from 'dayjs';
  import TransportChart from './components/TransportChart.vue';
  import RuleChart from './components/RuleChart.vue';
  import jsChart from './components/JsChart.vue';
  import StorageChart from './components/StorageChart.vue';
  import AlarmChart from './components/AlarmChart.vue';
  import NotificationChart from './components/NotificationChart.vue';
  import { historyCmdObject } from './components/TransportChart.data';
  import { useWsStore } from '/@/store/modules/thingsboard/ws';
  import { chartINT, entityDataCmds, findParams, latestDataCmds } from './index.data';

  const ruleStatsChartData = ref<any[]>([]);

  const chartData = ref<chartINT>({
    transportDataPointsCountHourly: {},
    ruleEngineExecutionCountHourly: {},
    jsExecutionCountHourly: {},
    storageDataPointsCountHourly: {},
    createdAlarmsCountHourly: {},
    emailCountHourly: {},
  });
  // 卡片数据
  const list = ref<any>({
    transportMsgCount: {
      title: '消息',
      key: 'transportMsgCount',
      value: 0,
    },
    transportDataPointsCount: {
      title: '数据点',
      key: 'transportDataPointsCount',
      value: 0,
    },
    ruleEngineExecutionCount: {
      title: '执行数',
      key: 'ruleEngineExecutionCount',
      value: 0,
    },
    jsExecutionCount: {
      title: 'JavaScript',
      key: 'jsExecutionCount',
      value: 0,
    },
    tbelExecutionCount: {
      title: 'Tbel',
      key: 'tbelExecutionCount',
      value: 0,
    },
    storageDataPointsCount: {
      title: '存储点天',
      key: 'storageDataPointsCount',
      value: 0,
    },
    createdAlarmsCount: {
      title: '创建告警数',
      key: 'createdAlarmsCount',
      value: 0,
    },
    emailCount: {
      title: '邮件',
      key: 'emailCount',
      value: 0,
    },
    smsCount: {
      title: '短信',
      key: 'smsCount',
      value: 0,
    },
  });
  // 时间
  const dateKey = ref<any>('day');
  // 时间范围
  const dateRange = ref<Array<number>>([]);
  const useStore = useWsStore();
  const go = useGo();
  const entityId = ref<any>();
  // 监听
  watch(
    () => dateKey.value,
    (nVal) => {
      sendAgain(nVal);
    },
    { immediate: false },
  );
  watch(
    () => dateRange.value,
    (nVal) => {
      sendAgain(null, nVal);
    },
    { immediate: false, deep: true },
  );
  // ws连接
  const { data, send, close } = useWebSocket(
    `ws://${import.meta.env.VITE_IP_PORT}/api/ws/plugins/telemetry?token=${localStorage.getItem('jwt_token')}`,
    {
      autoClose: false,
      autoReconnect: false,
      heartbeat: false,
      onMessage: () => {
        if (JSON.parse(data.value)?.data) {
          // 卡片初始化数据
          const { TIME_SERIES } = JSON.parse(data.value).data.data[0].latest;
          filterCardData(TIME_SERIES);
        } else if (JSON.parse(data.value)?.update[0]?.entityId?.entityType == 'API_USAGE_STATE') {
          // 实时更新数据处理
          const { latest, timeseries } = JSON.parse(data.value).update[0];
          if (latest?.TIME_SERIES) {
            const { TIME_SERIES } = latest;
            filterCardData(TIME_SERIES);
          }
          if (latest && timeseries) {
            Object.keys(timeseries).forEach((item) => {
              chartData.value.hasOwnProperty(item) && (chartData.value[item] = timeseries);
            });
          }
        } else if (JSON.parse(data.value)?.update[0]?.entityId?.entityType === 'ASSET') {
          JSON.parse(data.value).update.forEach((item) => {
            ruleStatsChartData.value.push({
              cmdId: JSON.parse(data.value).cmdId,
              name: item?.latest?.ENTITY_FIELD?.name?.value,
              value: item?.timeseries,
            });
          });
        }
      },
    },
  );
  // 详情路由
  function goDetails({ key }) {
    let data: any;
    const dateType = dateKey.value;
    let chartType = '';
    switch (key) {
      case 'transportMsgCount':
        data = chartData.value['transportDataPointsCountHourly'];
        chartType = 'transport';
        break;
      case 'transportDataPointsCount':
        data = chartData.value['transportDataPointsCountHourly'];
        chartType = 'transport';
        break;
      case 'ruleEngineExecutionCount':
        data = chartData.value['ruleEngineExecutionCountHourly'];
        chartType = 'rule';
        break;
      case 'jsExecutionCount':
        data = chartData.value['jsExecutionCountHourly'];
        chartType = 'js';
        break;
      case 'tbelExecutionCount':
        data = chartData.value['jsExecutionCountHourly'];
        chartType = 'js';
        break;
      case 'storageDataPointsCount':
        data = chartData.value['storageDataPointsCountHourly'];
        chartType = 'storage';
        break;
      case 'createdAlarmsCount':
        data = chartData.value['createdAlarmsCountHourly'];
        chartType = 'alarm';
        break;
      case 'emailCount':
        data = chartData.value['emailCountHourly'];
        chartType = 'notification';
        break;
      case 'smsCount':
        data = chartData.value['emailCountHourly'];
        chartType = 'notification';
        break;
    }
    go({
      name: 'apiDetail',
      params: {
        dateType,
        data: JSON.stringify(data),
        chartType,
      },
    });
  }
  // 首次上传
  async function initSend() {
    const { data } = await find(findParams);
    entityId.value = data[0].entityId;
    if ((data.length = 1)) {
      // 上传消息处理
      let cmdId = 1;
      entityDataCmds.forEach((item) => {
        item.cmdId = cmdId++;
        item.query.entityFilter =
          item.query.entityFilter?.type == 'assetType'
            ? item.query.entityFilter
            : {
                type: 'singleEntity',
                singleEntity: { ...data[0].entityId },
              };
        item.query.pageLink = {
          pageSize: item.query.latestValues.length == 0 ? 1024 : 1,
          page: 0,
          sortOrder: {
            key: {
              type: 'ENTITY_FIELD',
              key: 'createdTime',
            },
            direction: 'DESC',
          },
        };
        item.query.entityFields = [
          {
            type: 'ENTITY_FIELD',
            key: 'name',
          },
          {
            type: 'ENTITY_FIELD',
            key: 'label',
          },
          {
            type: 'ENTITY_FIELD',
            key: 'additionalInfo',
          },
        ];
      });
    }
    send(JSON.stringify({ entityDataCmds }));
  }
  // 重复上传
  async function sendAgain(dateKey: string | null, dateRange?: Array<number>) {
    if (dateKey) {
      switch (dateKey) {
        case 'day':
          // 最近一天
          latestDataCmds.forEach((item: any) => {
            if (item.tsCmd) {
              item.tsCmd.agg = item.cmdId == 15 ? 'NONE' : 'SUM';
              item.tsCmd.timeWindow = 24 * 60 * 60 * 1000;
              item.tsCmd.interval = 2 * 60 * 60 * 1000;
              item.tsCmd.startTs = getCurrentHourTimestamp('day') - 24 * 60 * 60 * 1000;
            }
          });
          break;
        case 'month':
          // 最近一个月
          latestDataCmds.forEach((item: any) => {
            if (item.tsCmd) {
              item.tsCmd.agg = item.cmdId == 15 ? 'NONE' : 'SUM';
              item.tsCmd.interval = item.cmdId == 15 ? null : 24 * 60 * 60 * 1000;
              item.tsCmd.timeWindow = 30 * 24 * 60 * 60 * 1000;
              item.tsCmd.interval = 24 * 60 * 60 * 1000;
              item.tsCmd.startTs = getCurrentHourTimestamp('month') - 30 * 24 * 60 * 60 * 1000;
            }
          });
          break;
        case 'year':
          // 最近一年
          latestDataCmds.forEach((item: any) => {
            if (item.tsCmd) {
              item.tsCmd.agg = item.cmdId == 15 ? 'NONE' : 'SUM';
              item.tsCmd.interval = item.cmdId == 15 ? null : 24 * 60 * 60 * 1000;
              item.tsCmd.timeWindow = 366 * 24 * 60 * 60 * 1000;
              item.tsCmd.interval = 30 * 24 * 60 * 60 * 1000;
              item.tsCmd.startTs = getCurrentHourTimestamp('year');
            }
          });
          break;
      }
      send(JSON.stringify({ entityDataCmds: latestDataCmds }));
    } else if (dateRange) {
      let interval = 0;
      const timeDiff = dateRange[1] - dateRange[0];
      if (timeDiff > 0 && timeDiff < 24 * 60 * 60 * 1000) {
        interval = 2 * 60 * 60 * 1000;
      } else if (timeDiff > 24 * 60 * 60 * 1000 && timeDiff < 30 * 24 * 60 * 60 * 1000) {
        interval = 24 * 60 * 60 * 1000;
      } else if (timeDiff > 30 * 24 * 60 * 60 * 1000 && timeDiff < 366 * 24 * 60 * 60 * 1000) {
        interval = 30 * 24 * 60 * 60 * 1000;
      }
      Object.keys(historyCmdObject).forEach((item) => {
        useStore.setCmdId();
        send(
          JSON.stringify({
            entityDataCmds: [
              {
                cmdId: useStore.getCmdId,
                query: {
                  entityFilter: {
                    type: 'singleEntity',
                    singleEntity: { ...entityId.value },
                  },
                  pageLink: {
                    pageSize: 1024,
                    page: 0,
                    sortOrder: {
                      key: {
                        type: 'ENTITY_FIELD',
                        key: 'createdTime',
                      },
                      direction: 'DESC',
                    },
                  },
                  latestValues: [],
                  entityFields: [
                    {
                      type: 'ENTITY_FIELD',
                      key: 'name',
                    },
                    {
                      type: 'ENTITY_FIELD',
                      key: 'label',
                    },
                    {
                      type: 'ENTITY_FIELD',
                      key: 'additionalInfo',
                    },
                  ],
                },
              },
            ],
          }),
        );
        historyCmdObject[item].cmdId = useStore.getCmdId;
        historyCmdObject[item].historyCmd.startTs = dateRange[0];
        historyCmdObject[item].historyCmd.endTs = dateRange[1];
        historyCmdObject[item].historyCmd.limit = 30;
        historyCmdObject[item].historyCmd.interval = interval;
        historyCmdObject[item].historyCmd.agg = 'SUM';
        send(JSON.stringify({ entityDataCmds: [historyCmdObject[item]] }));
      });
    }
  }
  // 获取时间戳
  function getCurrentHourTimestamp(dateKey: string) {
    const now = new Date();
    let currentTimestamp: any;
    if (dateKey === 'day') {
      currentTimestamp = new Date(
        now.getFullYear(),
        now.getMonth(),
        now.getDate(),
        now.getHours(),
        0,
        0,
      );
    } else if (dateKey == 'month') {
      currentTimestamp = new Date(now.getFullYear(), now.getMonth(), now.getDate(), 12, 0, 0);
    } else if (dateKey == 'year') {
      currentTimestamp = new Date(now.getFullYear() - 1, now.getMonth() + 1, 0, 0, 0, 0);
    }
    return currentTimestamp.getTime();
  }

  // 范围日期选择
  function handleChange(value: any) {
    if (value) {
      dateKey.value = null;
      value.forEach((item) => dateRange.value.push(dayjs(item).valueOf()));
    } else {
      dateKey.value = 'day';
    }
  }

  // 卡片数据过滤
  function filterCardData(TIME_SERIES: any) {
    if (!TIME_SERIES) return;
    const {
      transportMsgCount,
      transportDataPointsCount,
      ruleEngineExecutionCount,
      jsExecutionCount,
      tbelExecutionCount,
      storageDataPointsCount,
      createdAlarmsCount,
      emailCount,
      smsCount,
    } = TIME_SERIES;
    transportMsgCount && (list.value['transportMsgCount'].value = transportMsgCount.value);
    transportDataPointsCount &&
      (list.value['transportDataPointsCount'].value = transportDataPointsCount.value);
    ruleEngineExecutionCount &&
      (list.value['ruleEngineExecutionCount'].value = ruleEngineExecutionCount.value);
    jsExecutionCount && (list.value['jsExecutionCount'].value = jsExecutionCount.value);
    tbelExecutionCount && (list.value['tbelExecutionCount'].value = tbelExecutionCount.value);
    storageDataPointsCount &&
      (list.value['storageDataPointsCount'].value = storageDataPointsCount.value);
    createdAlarmsCount && (list.value['createdAlarmsCount'].value = createdAlarmsCount.value);
    emailCount && (list.value['emailCount'].value = emailCount.value);
    smsCount && (list.value['smsCount'].value = smsCount.value);
  }

  onMounted(async () => {
    ruleStatsChartData.value = [];
    await initSend();
    sendAgain('day');
  });
  onBeforeUnmount(() => close());
</script>

<style lang="less" scoped>
  html[data-theme='dark'] {
    .tab-box :deep(.ant-tabs-nav) {
      background-color: #000;
    }
  }

  :deep(.ant-tabs-nav) {
    background-color: #fff;
    margin-left: 20px;
    margin-right: 20px;
    margin-top: 20px;
    margin-bottom: 4px;
    height: 48px;
  }

  :deep(.ant-tabs-tab) {
    margin-left: 16px;
    margin-right: 16px;
  }

  :deep(.ant-tabs-content-holder) {
    margin-left: 4px;
    margin-right: 4px;
  }

  :deep(.ant-card-contain-grid:not(.ant-card-loading) .ant-card-body) {
    display: flex;
  }
</style>
